#include "stdafx.h"
#if LIT_OGRE_SUPPORT

#include <LitApplicationSettings.h>
#include <LitOgreManager.h>
#include <LitFileSystem.h>

Lit::ApplicationSettings Lit::ApplicationSettings::DEFAULTS()
{
	Lit::ApplicationSettings ret;
	Lit::MetaGroup				general(&ret,translateGroup(ASG_GENERAL));
#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
	general.setProperty( "Platform", "Android" );
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
	general.setProperty( "Platform", "Apple" );
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
	general.setProperty( "Platform", "Apple IOS" );
#elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
	general.setProperty( "Platform", "Linux" );
#elif OGRE_PLATFORM == OGRE_PLATFORM_NACL
	general.setProperty( "Platform", "Na CL" );
#elif OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#ifdef _W64
	general.setProperty( "Platform", "Windows x64" );
#else
	general.setProperty( "Platform", "Windows x86" );
#endif
#elif OGRE_PLATFORM == OGRE_PLATFORM_WINRT
	general.setProperty( "Platform", "Windows RT" );
#else
	general.setProperty( "Platform", "Other" );
#endif

#if defined(NDEBUG)
	general.setProperty("Debug", "false" );
#else
	general.setProperty("Debug", "true" );
#endif
	general.setProperty("Home", Lit::FileSystem::applicationPath());
	ret.setGroup( general);
	ret.setRenderSystemName( Lit::OgreManager::Direct3D9RenderSystem );
#if defined(NDEBUG)
	ret.setOgreProperty( "Plugins", "RenderSystem_Direct3D9 RenderSystem_Direct3D11 RenderSystem_GL3Plus Plugin_ParticleFX Plugin_CgProgramManager Plugin_OctreeSceneManager" );
	ret.setOgreProperty( "LogName", "LitFramework.log" );
#else
	ret.setOgreProperty( "Plugins", "RenderSystem_Direct3D9_d RenderSystem_Direct3D11_d RenderSystem_GL3Plus_d Plugin_ParticleFX_d Plugin_CgProgramManager_d Plugin_OctreeSceneManager_d" );
	ret.setOgreProperty( "LogName", "LitFramework_d.log" );
#endif
#ifndef NDEBUG
	bool fs = true;
#else
	bool fs = false;
#endif

	ret.setRenderSystemProperties( ASCL_LOWEST, 0, fs, 640, 480, 16, true, 60 );
	ret.setRenderSystemProperties( ASCL_LOW, 0, fs, 800, 600, 32, true, 60 );
	ret.setRenderSystemProperties( ASCL_MEDIUM, 0, fs, 1024, 768, 32, true, 60 );
	ret.setRenderSystemProperties( ASCL_HIGH, 0, fs, 1280, 768, 32, true, 60 );
	ret.setRenderSystemProperties( ASCL_HIGHEST, 0, fs, 1680, 1050, 32, true, 60 );

	return ret;
}
namespace Lit
{
	ApplicationSettings::ApplicationSettings(void)
		: MetaObject("Settings")
		, MetaObjectSerialiser( "ApplicationSettingsSerialiser" )
	{
		mProps = ApplicationSettings::DEFAULTS().mProps;
	}
	
	ApplicationSettings::ApplicationSettings( const ApplicationSettings& rk )
		: MetaObject(rk)
		, MetaObjectSerialiser(rk)
	{}

	ApplicationSettings::~ApplicationSettings(void)
	{
	}
	MetaGroup& ApplicationSettings::getGroup( ApplicationSettingsGroup grp )
	{
		return MetaObject::getGroup( translateGroup(grp) );
	}
	const MetaGroup& ApplicationSettings::getGroup( ApplicationSettingsGroup grp ) const
	{
		return MetaObject::getGroup( translateGroup(grp) );
	}
	String ApplicationSettings::translateGroup( ApplicationSettingsGroup grp )
	{
		switch( grp )
		{
		case ASG_OGRE: return "OGRE";
		case ASG_INPUT: return "Input";
		case ASG_GENERAL: 
		default:
			return "General";
		};
	}
	void ApplicationSettings::load( const String &filename )
	{
		try
		{
			MetaObject obj;
			FileStream strm( filename, Stream::TextRead );
			fromStream( StreamPtr(&strm), obj );
			strm.close();

			merge( obj, true );
		}
		catch( Exception e )
		{
			throw Lit::InitialisationError("Cannot load application settings because:\r\n\t"+e.error(), EXC_LOC);
		}
		catch( std::exception e )
		{
			throw Lit::InitialisationError("Cannot load application settings because:\r\n\t"+String(e.what()), EXC_LOC);
		}
		catch( ... )
		{
			throw Lit::LogicError("Cannot load application settings because an unknown error happened", EXC_LOC);
		}
	}

	void ApplicationSettings::save( const String &filename )
	{
		try
		{
			FileStream strm( filename, Stream::TextWrite );
			toStream( StreamPtr(&strm), *this );
			strm.close();
		}
		catch( Exception e )
		{
			throw Lit::LogicError("Cannot load application settings because:\r\n\t"+e.error(), EXC_LOC);
		}
		catch( std::exception e )
		{
			throw Lit::LogicError("Cannot load application settings because:\r\n\t"+String(e.what()), EXC_LOC);
		}
		catch( ... )
		{
			throw Lit::LogicError("Cannot load application settings because an unknown error happened", EXC_LOC);
		}
	}
	bool ApplicationSettings::hasGroup( ApplicationSettingsGroup grp ) const
	{
		return MetaObject::hasGroup( translateGroup( grp ) );
	}
	String ApplicationSettings::translateConfigLevel(ApplicationSettingsConfigLevel lvl)
	{
		switch( lvl )
		{
		case ASCL_LOW:
			return "Low";
		case ASCL_MEDIUM:
			return "Medium";
		case ASCL_HIGH:
			return "High";
		case ASCL_HIGHER:
			return "Higher";
		case ASCL_HIGHEST:
			return "Highest";
		case ASCL_LOWEST:
		default:
			return "Lowest";
		};
	}
	void ApplicationSettings::setRenderSystemProperties( 
		ApplicationSettingsConfigLevel lvl, 
		unsigned short fsaa,
		bool fullscreen,
		unsigned short width, unsigned short height,
		unsigned short bpp, 
		bool vsync,
		unsigned short refresh_rate )
	{
		setRenderSystemProperty<unsigned short>( lvl, "FSAA", fsaa );
		setRenderSystemProperty<unsigned short>( lvl, "ColourDepth", bpp );
		setRenderSystemProperty<String>( lvl, "Fullscreen", fullscreen?"Yes":"No" );
		setRenderSystemProperty<String>( lvl, "VSync", vsync?"Yes":"No" );
		setRenderSystemProperty<String>( lvl, "Resolution", String(width)(" x ")(height).str() );
		setRenderSystemProperty<unsigned short>( lvl, "RefreshRate", refresh_rate );
	}
	String ApplicationSettings::getRenderSystemConfigName(ApplicationSettingsConfigLevel lvl) const
	{
		return translateGroup( ASG_OGRE ) + "." + translateConfigLevel( lvl );
	}
	bool ApplicationSettings::hasRenderSystemConfig(ApplicationSettingsConfigLevel lvl) const
	{
		return MetaObject::hasGroup( getRenderSystemConfigName(lvl) );
	}
	MetaGroup& ApplicationSettings::getRenderSystemConfig( ApplicationSettingsConfigLevel lvl )
	{
		if( !hasRenderSystemConfig( lvl ) )
			return createRenderSystemConfig( lvl );
		return MetaObject::getGroup( getRenderSystemConfigName(lvl) );
	}
	const MetaGroup& ApplicationSettings::getRenderSystemConfig( ApplicationSettingsConfigLevel lvl ) const
	{
		return MetaObject::getGroup( getRenderSystemConfigName(lvl) );
	}
		
	void ApplicationSettings::setRenderSystemConfig( ApplicationSettingsConfigLevel lvl, const MetaGroup& g )
	{
		MetaGroup grp(g);
		grp.setName( translateGroup( ASG_OGRE ) + "." + translateConfigLevel( lvl ) );
		return setGroup( grp );
	}
	MetaGroup& ApplicationSettings::createRenderSystemConfig( ApplicationSettingsConfigLevel lvl )
	{
		if( !MetaObject::hasGroup( getRenderSystemConfigName(lvl) ) )
			setGroup( MetaGroup( this, getRenderSystemConfigName(lvl)) );
		return MetaObject::getGroup( getRenderSystemConfigName(lvl) );
	}
	String ApplicationSettings::getRenderSystemName( const String &def_name ) const
	{
		if( hasGroup(ASG_OGRE) ) return getGroup(ASG_OGRE).getProperty<String>("RenderSystem", def_name);
		return def_name;
	}
	void ApplicationSettings::setRenderSystemName( const String &name )
	{
		if( !hasGroup(ASG_OGRE) ) 
			setGroup( MetaGroup(this, translateGroup(ASG_OGRE)) );

		getGroup(ASG_OGRE).setProperty("RenderSystem", name);
	}
	
};


#endif